home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / admin / dig-2.0 / dig-2 / dig.2.0 / gethostnamadr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-04  |  8.3 KB  |  415 lines

  1.  
  2. /*
  3.  * Copyright (c) 1985, 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted
  7.  * provided that this notice is preserved and that due credit is given
  8.  * to the University of California at Berkeley. The name of the University
  9.  * may not be used to endorse or promote products derived from this
  10.  * software without specific prior written permission. This software
  11.  * is provided ``as is'' without express or implied warranty.
  12.  */
  13.  
  14. /*
  15. ** Updated 3/27/89 for 'dig' version 1.0 from University of Southern
  16. ** California Information Sciences Institute (USC-ISI).
  17. **
  18. ** Distributed with 'dig' version 2.0 release from USC-ISI (9/1/90).
  19. */
  20.  
  21.  
  22. #if defined(LIBC_SCCS) && !defined(lint)
  23. static char sccsid[] = "@(#)gethostnamadr.c    6.32 (Berkeley) 4/12/88";
  24. #endif /* LIBC_SCCS and not lint */
  25.  
  26. #include "hfiles.h"
  27. #include PARAMH
  28. #include <sys/socket.h>
  29. #include <netinet/in.h>
  30. #include <ctype.h>
  31. #include NETDBH
  32. #include <stdio.h>
  33. #include <errno.h>
  34. #include <arpa/inet.h>
  35. #include NAMESERH
  36. #ifndef T_TXT
  37. #define T_TXT 16
  38. #endif  T_TXT
  39. #include RESOLVH
  40.  
  41. #define    MAXALIASES    35
  42. #define    MAXADDRS    35
  43.  
  44. static char *h_addr_ptrs[MAXADDRS + 1];
  45.  
  46. static struct hostent host;
  47. static char *host_aliases[MAXALIASES];
  48. static char hostbuf[BUFSIZ+1];
  49. static struct in_addr host_addr;
  50. static char HOSTDB[] = "/etc/hosts";
  51. static FILE *hostf = NULL;
  52. static char hostaddr[MAXADDRS];
  53. static char *host_addrs[2];
  54. static int stayopen = 0;
  55. static char *any();
  56.  
  57. #if PACKETSZ > 1024
  58. #define    MAXPACKET    PACKETSZ
  59. #else
  60. #define    MAXPACKET    1024
  61. #endif
  62.  
  63. typedef union {
  64.     HEADER hdr;
  65.     u_char buf[MAXPACKET];
  66. } querybuf;
  67.  
  68. static union {
  69.     long al;
  70.     char ac;
  71. } align;
  72.  
  73.  
  74. int h_errno;
  75. extern errno;
  76.  
  77. static struct hostent *
  78. getanswer(answer, anslen, iquery)
  79.     querybuf *answer;
  80.     int anslen;
  81.     int iquery;
  82. {
  83.     register HEADER *hp;
  84.     register u_char *cp;
  85.     register int n;
  86.     u_char *eom;
  87.     char *bp, **ap;
  88.     int type, class, buflen, ancount, qdcount;
  89.     int haveanswer, getclass = C_ANY;
  90.     char **hap;
  91.  
  92.     eom = answer->buf + anslen;
  93.     /*
  94.      * find first satisfactory answer
  95.      */
  96.     hp = &answer->hdr;
  97.     ancount = ntohs(hp->ancount);
  98.     qdcount = ntohs(hp->qdcount);
  99.     bp = hostbuf;
  100.     buflen = sizeof(hostbuf);
  101.     cp = answer->buf + sizeof(HEADER);
  102.     if (qdcount) {
  103.         if (iquery) {
  104.             if ((n = dn_expand((char *)answer->buf, eom,
  105.                  cp, bp, buflen)) < 0) {
  106.                 h_errno = NO_RECOVERY;
  107.                 return ((struct hostent *) NULL);
  108.             }
  109.             cp += n + QFIXEDSZ;
  110.             host.h_name = bp;
  111.             n = strlen(bp) + 1;
  112.             bp += n;
  113.             buflen -= n;
  114.         } else
  115.             cp += dn_skipname(cp, eom) + QFIXEDSZ;
  116.         while (--qdcount > 0)
  117.             cp += dn_skipname(cp, eom) + QFIXEDSZ;
  118.     } else if (iquery) {
  119.         if (hp->aa)
  120.             h_errno = HOST_NOT_FOUND;
  121.         else
  122.             h_errno = TRY_AGAIN;
  123.         return ((struct hostent *) NULL);
  124.     }
  125.     ap = host_aliases;
  126.     host.h_aliases = host_aliases;
  127.     hap = h_addr_ptrs;
  128. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  129.     host.h_addr_list = h_addr_ptrs;
  130. #endif
  131.     haveanswer = 0;
  132.     while (--ancount >= 0 && cp < eom) {
  133.         if ((n = dn_expand((char *)answer->buf, eom, cp, bp, buflen)) < 0)
  134.             break;
  135.         cp += n;
  136.         type = _getshort(cp);
  137.          cp += sizeof(u_short);
  138.         class = _getshort(cp);
  139.          cp += sizeof(u_short) + sizeof(u_long);
  140.         n = _getshort(cp);
  141.         cp += sizeof(u_short);
  142.         if (type == T_CNAME) {
  143.             cp += n;
  144.             if (ap >= &host_aliases[MAXALIASES-1])
  145.                 continue;
  146.             *ap++ = bp;
  147.             n = strlen(bp) + 1;
  148.             bp += n;
  149.             buflen -= n;
  150.             continue;
  151.         }
  152.         if (iquery && type == T_PTR) {
  153.             if ((n = dn_expand((char *)answer->buf, eom,
  154.                 cp, bp, buflen)) < 0) {
  155.                 cp += n;
  156.                 continue;
  157.             }
  158.             cp += n;
  159.             host.h_name = bp;
  160.             return(&host);
  161.         }
  162.         if (iquery || type != T_A)  {
  163. #ifdef DEBUG
  164.             if (_res.options & RES_DEBUG)
  165.             printf("; ** unexpected answer type %d, size %d\n",
  166.                    type, n);
  167. #endif
  168.             cp += n;
  169.             continue;
  170.         }
  171.         if (haveanswer) {
  172.             if (n != host.h_length) {
  173.                 cp += n;
  174.                 continue;
  175.             }
  176.             if (class != getclass) {
  177.                 cp += n;
  178.                 continue;
  179.             }
  180.         } else {
  181.             host.h_length = n;
  182.             getclass = class;
  183.             host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
  184.             if (!iquery) {
  185.                 host.h_name = bp;
  186.                 bp += strlen(bp) + 1;
  187.             }
  188.         }
  189.  
  190.         bp += sizeof(align) - ((u_long)bp % sizeof(align));
  191.  
  192.         if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
  193. #ifdef DEBUG
  194.             if (_res.options & RES_DEBUG)
  195.                 printf("; ** size (%d) too big\n", n);
  196. #endif
  197.             break;
  198.         }
  199.         bcopy(cp, *hap++ = bp, n);
  200.         bp +=n;
  201.         cp += n;
  202.         haveanswer++;
  203.     }
  204.     if (haveanswer) {
  205.         *ap = NULL;
  206. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  207.         *hap = NULL;
  208. #else
  209.         host.h_addr = h_addr_ptrs[0];
  210. #endif
  211.         return (&host);
  212.     } else {
  213.         h_errno = TRY_AGAIN;
  214.         return ((struct hostent *) NULL);
  215.     }
  216. }
  217.  
  218. struct hostent *
  219. gethostbyname(name)
  220.     char *name;
  221. {
  222.     querybuf buf;
  223.     register char *cp;
  224.     int n;
  225.     struct hostent *gethostdomain();
  226.     extern struct hostent *_gethtbyname();
  227.  
  228.     /*
  229.      * disallow names consisting only of digits/dots, unless
  230.      * they end in a dot.
  231.      */
  232.     if (isdigit(name[0]))
  233.         for (cp = name;; ++cp) {
  234.             if (!*cp) {
  235.                 if (*--cp == '.')
  236.                     break;
  237.                 h_errno = HOST_NOT_FOUND;
  238.                 return ((struct hostent *) NULL);
  239.             }
  240.             if (!isdigit(*cp) && *cp != '.') 
  241.                 break;
  242.         }
  243.  
  244.     if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
  245. #ifdef DEBUG
  246.         if (_res.options & RES_DEBUG)
  247.             printf("; ** res_search failed\n");
  248. #endif
  249.         if (errno == ECONNREFUSED)
  250.             return (_gethtbyname(name));
  251.         else
  252.             return ((struct hostent *) NULL);
  253.     }
  254.     return (getanswer(&buf, n, 0));
  255. }
  256.  
  257. struct hostent *
  258. gethostbyaddr(addr, len, type)
  259.     char *addr;
  260.     int len, type;
  261. {
  262.     int n;
  263.     querybuf buf;
  264.     register struct hostent *hp;
  265.     char qbuf[MAXDNAME];
  266.     extern struct hostent *_gethtbyaddr();
  267.     
  268.     if (type != AF_INET)
  269.         return ((struct hostent *) NULL);
  270.     (void) sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa",
  271.         ((unsigned)addr[3] & 0xff),
  272.         ((unsigned)addr[2] & 0xff),
  273.         ((unsigned)addr[1] & 0xff),
  274.         ((unsigned)addr[0] & 0xff));
  275.     n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf));
  276.     if (n < 0) {
  277. #ifdef DEBUG
  278.         if (_res.options & RES_DEBUG)
  279.             printf(";; ** res_query failed\n");
  280. #endif
  281.         if (errno == ECONNREFUSED)
  282.             return (_gethtbyaddr(addr, len, type));
  283.         return ((struct hostent *) NULL);
  284.     }
  285.     hp = getanswer(&buf, n, 1);
  286.     if (hp == NULL)
  287.         return ((struct hostent *) NULL);
  288.     hp->h_addrtype = type;
  289.     hp->h_length = len;
  290.     h_addr_ptrs[0] = (char *)&host_addr;
  291.     h_addr_ptrs[1] = (char *)0;
  292.     host_addr = *(struct in_addr *)addr;
  293.     return(hp);
  294. }
  295.  
  296. _sethtent(f)
  297.     int f;
  298. {
  299.     if (hostf == NULL)
  300.         hostf = fopen(HOSTDB, "r" );
  301.     else
  302.         rewind(hostf);
  303.     stayopen |= f;
  304. }
  305.  
  306. _endhtent()
  307. {
  308.     if (hostf && !stayopen) {
  309.         (void) fclose(hostf);
  310.         hostf = NULL;
  311.     }
  312. }
  313.  
  314. struct hostent *
  315. _gethtent()
  316. {
  317.     char *p;
  318.     register char *cp, **q;
  319.  
  320.     if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL)
  321.         return (NULL);
  322. again:
  323.     if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL)
  324.         return (NULL);
  325.     if (*p == '#')
  326.         goto again;
  327.     cp = any(p, "#\n");
  328.     if (cp == NULL)
  329.         goto again;
  330.     *cp = '\0';
  331.     cp = any(p, " \t");
  332.     if (cp == NULL)
  333.         goto again;
  334.     *cp++ = '\0';
  335.     /* THIS STUFF IS INTERNET SPECIFIC */
  336. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  337.     host.h_addr_list = host_addrs;
  338. #endif
  339.     host.h_addr = hostaddr;
  340.     *((u_long *) host.h_addr) = inet_addr(p);
  341.     host.h_length = sizeof (u_long);
  342.     host.h_addrtype = AF_INET;
  343.     while (*cp == ' ' || *cp == '\t')
  344.         cp++;
  345.     host.h_name = cp;
  346.     q = host.h_aliases = host_aliases;
  347.     cp = any(cp, " \t");
  348.     if (cp != NULL) 
  349.         *cp++ = '\0';
  350.     while (cp && *cp) {
  351.         if (*cp == ' ' || *cp == '\t') {
  352.             cp++;
  353.             continue;
  354.         }
  355.         if (q < &host_aliases[MAXALIASES - 1])
  356.             *q++ = cp;
  357.         cp = any(cp, " \t");
  358.         if (cp != NULL)
  359.             *cp++ = '\0';
  360.     }
  361.     *q = NULL;
  362.     return (&host);
  363. }
  364.  
  365. static char *
  366. any(cp, match)
  367.     register char *cp;
  368.     char *match;
  369. {
  370.     register char *mp, c;
  371.  
  372.     while (c = *cp) {
  373.         for (mp = match; *mp; mp++)
  374.             if (*mp == c)
  375.                 return (cp);
  376.         cp++;
  377.     }
  378.     return ((char *)0);
  379. }
  380.  
  381. struct hostent *
  382. _gethtbyname(name)
  383.     char *name;
  384. {
  385.     register struct hostent *p;
  386.     register char **cp;
  387.     
  388.     _sethtent(0);
  389.     while (p = _gethtent()) {
  390.         if (strcasecmp(p->h_name, name) == 0)
  391.             break;
  392.         for (cp = p->h_aliases; *cp != 0; cp++)
  393.             if (strcasecmp(*cp, name) == 0)
  394.                 goto found;
  395.     }
  396. found:
  397.     _endhtent();
  398.     return (p);
  399. }
  400.  
  401. struct hostent *
  402. _gethtbyaddr(addr, len, type)
  403.     char *addr;
  404.     int len, type;
  405. {
  406.     register struct hostent *p;
  407.  
  408.     _sethtent(0);
  409.     while (p = _gethtent())
  410.         if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
  411.             break;
  412.     _endhtent();
  413.     return (p);
  414. }
  415.